package com.corpgovernment.common.aspect;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.linktrace.HttpLinkTraceAspect;
import com.ctrip.corp.obt.generic.utils.EnvironmentHolder;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.metric.Metrics;
import com.ctrip.corp.obt.metric.spectator.api.Id;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author zl.cui
 * @date 2023/2/21
 */
@Order(-2000)
@ControllerAdvice(annotations = RestController.class)
@ResponseBody
@Slf4j
public class CorpBusinessExceptionAdvice {
    @Autowired
    private HttpLinkTraceAspect httpLinkTraceAspect;

    Id responseCodeId = Metrics.REGISTRY.createId("common.aspect.responseCode");
    @ExceptionHandler(value = CorpBusinessException.class)
    public ResponseEntity<Object> errorHandler(CorpBusinessException exception, HttpServletRequest request) {
        JSONObject json = new JSONObject();
        String msg ;
        json.put("status", exception.getResultCode());
        if (StringUtils.isEmpty(exception.getMsg())) {
            msg = "服务器忙，请稍后重试";
            json.put("msg", msg);
        } else {
            msg = exception.getMsg();
            json.put("msg", msg);
        }
        recordMetric(exception, request);
        log.warn(StrUtil.format("Request url: {}. response: {}", getRpc(request), json), exception);
        httpLinkTraceAspect.updateHttpLinkTrace(getRpc(request), json);
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-RC", Optional.ofNullable(exception.getResultCode()).map(String::valueOf).orElse("0"));
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(json, headers,
                HttpStatus.OK);
    }

    private void recordMetric(CorpBusinessException exception, HttpServletRequest request){
        Map<String, String> tags = new HashMap<>();
        tags.put("responseCode", String.valueOf(exception.getResultCode()));
        tags.put("application", EnvironmentHolder.getApplicationName());
        tags.put("rpc", getRpc(request));
        Metrics.REGISTRY.counter(responseCodeId.withTags(tags)).increment();
    }

    private String getRpc(HttpServletRequest request){
        if (request == null || StrUtil.isEmpty(request.getRequestURI())) {
            return "unknown";
        }
        return request.getRequestURI();
    }

}
